<?php
/**
 * Mapper class for user entity
 * 
 * @package disputeo
 * @version 1.0
 * @author jimmy.dixon
 */

class Application_Model_UserMapper
{
    /**
     * @var Zend_Db_Table_Abstract
     */
    protected $_dbTable;

    /**
     * @param Zend_Db_Table_Abstract $dbtable
     */
    public function __construct($dbtable = null)
    {
        if ($dbtable instanceof Zend_Db_Table_Abstract) {
            $this->_dbTable = new $dbtable();
        } else {
            $this->_dbTable = new Application_Model_DbTable_Users();
        }
    }

    /**
     * Create new user.
     * @param array $data
     * @return Application_Model_User 
     */
    public function create(array $data = array())
    {
        $user = new Application_Model_User($data);
        $this->save($user);
        return $user;
    }

    /**
     * Update or create a user.
     * @param Application_Model_User $user 
     */
    public function save(Application_Model_User $user)
    {
        $data = $user->toArray();
        $id = $user->getId();
        if ($id) {
            $this->_dbTable->update($data, array('id = ?' => $id));
        } else {
            $this->_dbTable->insert($data);
        }
        if ($user->hasPasswordReset()) {
            $this->savePasswordReset($user->getPasswordReset());
        }
    }

    /**
     * Find user by primary key.
     * @param integer $id
     * @return Application_Model_User 
     */
    public function find($id = null)
    {
        $result = $this->_dbTable->find($id);
        if (0 == count($result)) {
            return null;
        }
        $row = $result->current();
        return new Application_Model_User($row->toArray());
    }

    /**
     * Find user by email address.
     * @param string $email
     * @return Application_Model_User 
     */
    public function findWhereEmailIs($email = null)
    {
        $row = $this->_dbTable->fetchRow("email = '$email'");
        if (empty($row)) {
            return null;
        }
        return new Application_Model_User($row->toArray());
    }

    /**
     * Find user by password reset token.
     * @param type $hash
     * @return Application_Model_User
     */
    public function findWhereResetIdIs($hash = null)
    {
        $table = $this->_dbTable->getPasswordResetTable();
        $where = $table->select()->where('reset_id = ?', $hash);
        $resetData = $table->fetchRow($where);
        if (empty($resetData)) {
            return null;
        }
        $reset = new Application_Model_UserPasswordReset($resetData->toArray());
        $userData = $resetData->findParentRow(get_class($this->_dbTable));
        $user = new Application_Model_User($userData->toArray());
        $user->setPasswordReset($reset);
        return $user;
    }

    /**
     * Fetch all the users.
     * @return array $users 
     */
    public function fetchAll()
    {
        $resultSet = $this->_dbTable->fetchAll();
        $users = array();
        foreach ($resultSet as $row) {
            $user = new Application_Model_User($row->toArray());
            $users[] = $user;
        }
        return $users;
    }

    /**
     * Save a user password reset token.
     * @param Application_Model_UserPasswordReset $reset 
     */
    public function savePasswordReset(Application_Model_UserPasswordReset $reset)
    {
        $table = $this->_dbTable->getPasswordResetTable();
        $id = $reset->getResetId();
        $userId = $reset->getUserId();
        if (!is_null($reset->getCreated())) {
            $table->update($reset->toArray(), array('reset_id = ?' => $id));
        } else {
            $where = $table->getAdapter()->quoteInto('user_id = ?', $userId);
            $table->update(array('used' => 1), $where);
            $table->insert($reset->toArray());
        }
    }

    /**
     * Create a password reset token for a user.
     * @param Application_Model_User $user 
     */
    public function createPasswordReset(Application_Model_User $user)
    {
        $userId = $user->getId();
        $reset = new Application_Model_UserPasswordReset();
        $reset->setUserId($userId)
            ->setResetId(sha1($userId . time()));
        $this->savePasswordReset($reset);
        $user->setPasswordReset($reset);
    }

    /**
     * Get an authentication adapter for a user.
     * @param Application_Model_User $user
     * @return Zend_Auth_Adapter_DbTable 
     */
    public function getAuthAdapter(Application_Model_User $user)
    {
        $dbAdapter = $this->_dbTable->getAdapter();
        $authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
        $authAdapter->setTableName($this->_dbTable->getName())
            ->setIdentityColumn('username')
            ->setCredentialColumn('password')
            ->setCredentialTreatment('SHA1(CONCAT(?, password_salt))');
        $authAdapter->setIdentity($user->getUsername())
            ->setCredential($user->getPassword());
        return $authAdapter;
    }
}